/**
 * PMXCrossover.java
 * Class representing a partially matched (PMX) crossover operator
 * @author Antonio J. Nebro
 * @version 1.0
 */
package jmetal.base.operator.crossover;

import TeamPursuit.MensTeamPursuit;
import TeamPursuit.SimulationResult;
import TeamPursuit.WomensTeamPursuit;
import P3.Strategy;
import java.util.ArrayList;
import java.util.Properties;
import java.util.Random;
import java.util.logging.Level;
import java.util.logging.Logger;
import jmetal.base.*;
import jmetal.base.variable.*;
import jmetal.util.Configuration;
import jmetal.util.JMException;
import jmetal.util.PseudoRandom;

/**
 * This class allows to apply a PMX crossover operator using two parent
 * solutions.
 * NOTE: the operator is applied to the first variable of the solutions, and
 * the type of those variables must be VariableType_.Permutation.
 */
public class MyCrossover extends Crossover {

    private static final double pOnPacing = 0.2;

    /**
     * Perform the crossover operation
     * @param probability Crossover probability
     * @param parent1 The first parent
     * @param parent2 The second parent
     * @return An array containig the two offsprings
     * @throws JMException
     */
    public Solution[] doCrossover(double probability,
            Solution parent1,
            Solution parent2) throws JMException {

        Solution[] offspring = new Solution[2];
        
            offspring[0] = new Solution(parent1);
            offspring[1] = new Solution(parent2);
        
        SimulationResult result = null;
        Random r = new Random();
        Strategy str1 = (Strategy) parent1.getDecisionVariables()[0].deepCopy();
        Strategy str2 = (Strategy) parent2.getDecisionVariables()[0].deepCopy();

        ArrayList<Integer[]> pacing = new ArrayList<Integer[]>();
        ArrayList<Boolean[]> transition = new ArrayList<Boolean[]>();


        if (r.nextDouble() <= probability)//do the transaction cross
        {


            Strategy str1copy = (Strategy) str1.deepCopy();
            Strategy str2copy = (Strategy) str2.deepCopy();
            pacing = cross(str1copy.getPacing(), str2copy.getPacing());
            if (r.nextDouble() < pOnPacing) {
                transition = cross(str1copy.getTransition(), str2copy.getTransition());
            }
            else{
              transition.add(this.transferBol2(str1.getTransition()));
              transition.add(this.transferBol2(str2.getTransition()));
            }




            Strategy newStr1 = new Strategy(this.transferBol(transition.get(0)), this.transferInt(pacing.get(0)));            
            Variable[] var1 = new Variable[1];            
            var1[0] = newStr1;           
            offspring[0].setDecisionVariables(var1);
            Strategy newStr2 = new Strategy(this.transferBol(transition.get(1)), this.transferInt(pacing.get(1)));
            Variable[] var2 = new Variable[1];
            var2[0] = newStr2;
            offspring[1].setDecisionVariables(var2);
            //System.out.println(i+" "+offspring[i].toString());



        }

        // else
        return offspring;
    } // doCrossover

    private ArrayList<Integer[]> cross(int[] a, int[] b) {
        Random r = new Random();
        int t;
        int position1 = r.nextInt(a.length);
        int position2 = r.nextInt(a.length);
        while (position1 == position2) {
            position2 = r.nextInt(a.length);
        }
        if (position1 > position2) {
            t = position1;
            position1 = position2;
            position2 = t;
        }
        int temp;
        for (int i = position1; i <= position2; i++) {
            temp = a[i];
            a[i] = b[i];
            b[i] = temp;
        }
        ArrayList<Integer[]> toReturn = new ArrayList<Integer[]>();

        Integer[] aa = new Integer[a.length];
        Integer[] bb = new Integer[b.length];
        for (int i = 0; i < a.length; i++) {
            aa[i] = a[i];
            bb[i] = b[i];
        }

        toReturn.add(aa);
        toReturn.add(bb);
        return toReturn;
    }

    private ArrayList<Boolean[]> cross(boolean[] a, boolean[] b) {
        Random r = new Random();
        int t;
        int position1 = r.nextInt(a.length);
        int position2 = r.nextInt(a.length);
        while (position1 == position2) {
            position2 = r.nextInt(a.length);
        }
        if (position1 > position2) {
            t = position1;
            position1 = position2;
            position2 = t;
        }
        boolean temp;
        for (int i = position1; i <= position2; i++) {
            temp = a[i];
            a[i] = b[i];
            b[i] = temp;
        }
        ArrayList<Boolean[]> toReturn = new ArrayList<Boolean[]>();

        Boolean[] aa = new Boolean[a.length];
        Boolean[] bb = new Boolean[b.length];
        for (int i = 0; i < a.length; i++) {
            aa[i] = a[i];
            bb[i] = b[i];
        }

        toReturn.add(aa);
        toReturn.add(bb);
        return toReturn;
    }

    /**
     * Executes the operation
     * @param object An object containing an array of two solutions
     * @throws JMException
     */
    public Object execute(Object object) throws JMException {
        Solution[] parents = (Solution[]) object;
        Double crossoverProbability = null;


        //crossoverProbability = (Double)parameters_.get("probability");
        crossoverProbability = (Double) getParameter("probability");

        if (parents.length < 2) {
            Configuration.logger_.severe("PMXCrossover.execute: operator needs two "
                    + "parents");
            Class cls = java.lang.String.class;
            String name = cls.getName();
            throw new JMException("Exception in " + name + ".execute()");
        } else if (crossoverProbability == null) {
            Configuration.logger_.severe("PMXCrossover.execute: probability not "
                    + "specified");
            Class cls = java.lang.String.class;
            String name = cls.getName();
            throw new JMException("Exception in " + name + ".execute()");
        }

        Solution[] offspring = doCrossover(crossoverProbability.doubleValue(),
                parents[0],
                parents[1]);

        return offspring;
    } // execute

    private boolean isValid(SimulationResult result) {
        if (result.getProportionCompleted() < 0.9999998) {
            return false;
        } else {
            return true;
        }
    }

    private int[] transferInt(Integer[] a) {
        int[] toReturn = new int[a.length];
        for (int i = 0; i < a.length; i++) {
            toReturn[i] = a[i];
        }
        return toReturn;
    }

    private boolean[] transferBol(Boolean[] a) {
        boolean[] toReturn = new boolean[a.length];
        for (int i = 0; i < a.length; i++) {
            toReturn[i] = a[i];
        }
        return toReturn;
    }
    private Boolean[] transferBol2(boolean[] a) {
        Boolean[] toReturn = new Boolean[a.length];
        for (int i = 0; i < a.length; i++) {
            toReturn[i] = a[i];
        }
        return toReturn;
    }
} // PMXCrossover

